package utils

import (
	"strings"
)

func boolFunc[T any](cond bool, v1 T, v2 T) T {
	if cond {
		return v1
	} else {
		return v2
	}
}

func toString(arr []int8) string {
	temp := make([]byte, len(arr))
	for i := 0; i < len(arr); i++ {
		if arr[i] == '.' {
			arr[i] = '.'
		} else if arr[i] == -1 {
			arr[i] = '-'
		} else {
			arr[i] += '0'
		}
		temp[i] = byte(arr[i])
	}
	return string(temp)
}

func toArr(s string) []int8 {
	sLen := len(s)

	res := make([]int8, sLen)
	for i := 0; i < sLen; i++ {
		if s[i] == '.' {
			res[i] = '.'
		} else if s[i] == '-' {
			res[i] = -1
		} else {
			res[i] = int8(s[i] - '0')
		}
	}
	return res
}

/*
向数组尾部追加bit位的0，填充对齐
*/
func appendTailZero(n1 []int8, bit int) []int8 {
	for i := bit; i > 0; i-- {
		n1 = append(n1, 0)
	}
	return n1
}

/*
向数组头部追加bit位的0，填充对齐
*/
func appendHeadZero(n1 []int8, bit int) []int8 {
	res := make([]int8, len(n1)+bit)
	i := 0
	for ; i < bit; i++ {
		res[i] = 0
	}
	for ; i < bit+len(n1); i++ {
		res[i] = n1[i-bit]
	}
	return res
}

/*
丢弃头部的0
*/
func dropArrHeadZero(arr []int8) []int8 {
	aLen := len(arr)
	index := 0
	for i := 0; i < aLen; i++ {
		if arr[i] != 0 {
			break
		}
		index = i
	}
	return arr[index:]
}

func dropArrTailZero(arr []int8) []int8 {
	index := len(arr)
	for i := index - 1; i >= 0; i-- {
		if arr[i] != 0 {
			break
		}
		index = i
	}
	return arr[:index]
}

/*
只适用于整数，比较小数的话需要位数对齐
*/
func biggerThan(n1 []int8, n2 []int8) bool {
	l1, l2 := len(n1), len(n2)
	if l1 == l2 {
		for i := 0; i < l1; i++ {
			if n1[i] > n2[i] {
				return true
			}
			if n1[i] < n2[i] {
				return false
			}
		}
		return false
	}
	return l1 > l2
}

/*
只适用于整数，比较小数的话需要位数对齐
*/
func smallerThan(n1 []int8, n2 []int8) bool {
	l1, l2 := len(n1), len(n2)
	if l1 == l2 {
		for i := 0; i < l1; i++ {
			if n1[i] > n2[i] {
				return false
			}
			if n1[i] < n2[i] {
				return true
			}
		}
		return false
	}
	return l1 < l2
}

/*
只适用于正数，比较小数的话需要位数对齐
*/
func equals(n1 []int8, n2 []int8) bool {
	l1, l2 := len(n1), len(n2)

	if l1 == l2 {
		for i := 0; i < l1; i++ {
			if n1[i] != n2[i] {
				return false
			}
		}
		return true
	}
	return false
}

var (
	ZERO = []int8{0}
	ONE  = []int8{1}
)

const (
	PLUS            int8 = '+'
	SUB             int8 = '-'
	MULTIPLY        int8 = '*'
	DIVIDE          int8 = '/'
	REMINDER        int8 = '%'
	maxBit               = 100
	makeFloatSuffix      = ".0"
)

func isNegative(arr []int8) bool {
	return arr[0] == -1
}

func isPositive(arr []int8) bool {
	return !isNegative(arr) && !isZero(arr)
}

func isZero(arr []int8) bool {
	for i := 0; i < len(arr); i++ {
		if arr[i] != 0 {
			return false
		}
	}
	return true
}

/*
设置为负数，只适用于正数
*/
func setNegative(arr []int8) []int8 {
	if isNegative(arr) {
		return arr
	}
	alen := len(arr)
	res := make([]int8, alen+1)
	res[0] = -1
	for i := 1; i < alen+1; i++ {
		res[i] = arr[i-1]
	}
	return res
}

/*
设置为负数，只适用于负数
*/
func setPositive(arr []int8) []int8 {
	if isPositive(arr) {
		return arr
	}
	return arr[1:]
}

/*
大数乘一个数并右移bit位，只适用于正整数
*/
func integerMultiply(arr []int8, n int8, bit int) []int8 {
	oLen := len(arr)
	res := make([]int8, oLen+1)
	for i := 0; i < oLen; i++ {
		temp := arr[oLen-1-i]*n + res[oLen-i]
		if temp > 9 {
			res[oLen-i] = temp % 10
			res[oLen-1-i] += temp / 10
		} else {
			res[oLen-i] = temp
		}
	}
	for i := 0; i < bit; i++ {
		res = append(res, 0)
	}

	return res
}

func floatDivide10(arr []int8, bit int) []int8 {
	aLen := len(arr)
	if aLen > bit {
		return mergeFloat(arr[:aLen-bit], arr[aLen-bit:])
	} else {
		return mergeFloat(ZERO, appendHeadZero(arr, bit-aLen))
	}
}

/*
浮点数拆分成整数和小数部分，只适用于正浮点数
*/
func toFloatArr(s string) (integer []int8, decimal []int8) {
	ss := strings.Split(s, ".")
	return toArr(ss[0]), toArr(ss[1])
}

/*
合并整数和小数部分不包括点
*/
func mergeFloatNoDot(n1 []int8, n2 []int8) []int8 {
	l1, l2 := len(n1), len(n2)
	rLen := l1 + l2
	res := make([]int8, rLen)
	var i = rLen - 1
	for j := l2 - 1; j >= 0; j-- {
		res[i] = n2[j]
		i--
	}
	for j := l1 - 1; j >= 0; j-- {
		res[i] = n1[j]
		i--
	}
	return res
}

/*
合并整数和小数部分包括点
*/
func mergeFloat(n1 []int8, n2 []int8) []int8 {
	l1, l2 := len(n1), len(n2)
	rLen := l1 + l2 + 1
	res := make([]int8, rLen)
	var i = rLen - 1
	for j := l2 - 1; j >= 0; j-- {
		res[i] = n2[j]
		i--
	}
	res[i] = '.'
	i--
	for j := l1 - 1; j >= 0; j-- {
		res[i] = n1[j]
		i--
	}
	return res
}

/*
整数和小数部分合并，可能会存在进位，只适用于正浮点数加法
*/
func integerPlusFloat(n1 []int8, n2 []int8, carryBit bool) []int8 {
	if carryBit {
		return mergeFloat(bigIntegerPlus0(n1, ONE), n2)
	} else {
		return mergeFloat(n1, n2)
	}
}

/*
整数和小数部分合并，可能会存在进位，只适用于正浮点数减法
*/
func integerSubFloat(n1 []int8, n2 []int8, carryBit bool) []int8 {
	if carryBit {
		n2 = setPositive(n2)
		if isNegative(n1) {
			return mergeFloat(n1, n2)
		} else {
			return mergeFloat(bigIntegerSub0(n1, ONE), floatSub(n2))
		}
	} else {
		if isNegative(n1) {
			if isZero(n2) {
				return mergeFloat(n1, n2)
			} else {
				return setNegative(mergeFloat(bigIntegerSub0(setPositive(n1), ONE), floatSub(n2)))
			}
		} else {
			return mergeFloat(n1, n2)
		}
	}
}

func floatSub(float []int8) []int8 {
	fLen := len(float)
	temp := make([]int8, fLen+1)
	temp[0] = 1
	temp = bigIntegerSub0(temp, float)
	return temp[len(temp)-fLen:]
}

func isFloat(s string) bool {
	return strings.ContainsAny(s, ".")
}
